有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么在JavaFX8中选择CheckboxTableCell时SelectedStateCallback不起作用?

我创建了演示,向我展示了问题:

package util;

import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;

    public class Demo extends Application {

        @Override
        public void start(Stage stage) throws Exception {

            ObservableList<Domain> data = FXCollections.observableArrayList(new Domain(true), new Domain(false), new Domain(true));

            TableView<Domain> tableView = new TableView<>(data);

            tableView.setEditable(true);
            tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);

            TableColumn column = new TableColumn("Completed");
            column.setEditable(true);
            column.setCellValueFactory(new PropertyValueFactory<>("completed"));

            column.setCellFactory(new Callback<TableColumn, TableCell>() {
                public TableCell call(TableColumn p) {
                    CheckBoxTableCell checkBoxTableCell = new CheckBoxTableCell();

                    checkBoxTableCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
                        @Override
                        public ObservableValue<Boolean> call(Integer index) {
                            Domain domain = data.get(index);
                            System.out.println("index=" + index + " " + domain);
                            return domain.getCompleted();
                        }
                    });

                    return checkBoxTableCell;
                }
            });

            tableView.getColumns().add(column);

            Scene scene = new Scene(tableView, 300, 300);
            stage.setTitle("ToDoList");
            stage.setScene(scene);
            stage.show();
        }

        public class Domain {
            private SimpleBooleanProperty completed;

            public Domain(boolean b) {
                super();
                this.completed = new SimpleBooleanProperty(b);
            }

            public SimpleBooleanProperty getCompleted() {
                return completed;
            }

            public void setCompleted(SimpleBooleanProperty completed) {
                this.completed = completed;
            }

            @Override
            public String toString() {
                return "Domain [completed=" + completed + "]";
            }

        }

        public static void main(String[] args) {
            launch(args);
        }
    }

所以,当您运行它时,您可以看到带有复选框的表。我的问题是在单击particluar复选框时获取正确的Domain对象。 表根据Domain.completed值显示复选框的状态。 单击复选框时,我想从TableView.items获取相应的域对象

我试图使用checkBoxTableCell.setSelectedStateCallback,但它只在启动时启动,而不是在单击复选框时启动


共 (1) 个答案

  1. # 1 楼答案

    selectedStateCallback提供了BooleanProperty的所选状态(双向)绑定到的CheckBox。因此,在代码中,您已确保复选框始终表示在Domain对象中定义为completed的属性的值。因此,您可以只侦听这些属性的更改:

    for (int i = 0; i < data.size(); i++) {
        final String item = "Item "+i ;
        Domain d = data.get(i);
        d.getCompleted().addListener((obs, wasCompleted, isNowCompleted) -> {
            System.out.println("Completed state for "+item+" changed from "+wasCompleted+" to "+isNowCompleted);
        });
    }
    

    相反,如果在外部更改属性,复选框将更新:

    Button selectAll = new Button("Select all");
    selectAll.setOnAction(e -> 
        data.forEach(domain -> domain.getCompleted().set(true)));
    

    另外,您的模型应该遵循JavaFX Properties pattern。在当前的实现中,如果对列表中的对象调用setCompleted(...),则会破坏复选框功能(因为复选框将绑定到错误的属性)。你需要:

    public class Domain {
        private final BooleanProperty completed ;
    
        public Domain(boolean completed) {
            this.completed = new SimpleBooleanProperty(completed);
        }
    
        public BooleanProperty completedProperty() {
            return completed ;
        }
    
        public final boolean isCompleted() {
            return completedProperty().get();
        }
    
        public final void setCompleted(boolean completed) {
            completedProperty().set(completed);
        }
    }
    

    随着selectedStateCallback中相应的更改:

    return domain.completedProperty();